package com.example.android.jmatt.acc;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;


public class FileReaderWorker extends Thread {
    
    private static FileReaderWorker worker;
    private Handler mHandler;
    private HashMap<Job, Handler> mCallbackMap = new HashMap<Job, Handler>();
    
    private FileReaderWorker() {
        
    }
    
    public static synchronized FileReaderWorker getInstance() {
        if (worker == null) {
            worker = new FileReaderWorker();
            worker.start();
        }
        return worker;
    }
    
    public void run() {
        Looper.prepare();
        
        mHandler = new Handler() {
          public void handleMessage(Message msg) {
              readInput((Job) msg.obj);
              Message resp = mCallbackMap.get((Job) msg.obj).obtainMessage();
              resp.obj = msg.obj;
              resp.sendToTarget();
          }
        };
        
        Looper.loop();
    }
    
    public static void readStream(Job in, Handler whenFinished) {
        while (getInstance().mHandler == null) {
            // the handler will only be set after the thread starts up, wait for it
            // TODO busy waiting is bad, do something smarter
            try {
                Thread.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        Message msg = getInstance().mHandler.obtainMessage();
        msg.obj = in;
        getInstance().mCallbackMap.put(in, whenFinished);
        msg.sendToTarget();
    }
    
    private void readInput(Job in) {
        // TODO how could we make this more efficient?
        byte[] allBytes = new byte[0];
        int bytesRead = -1;
        int totalBytes = 0;

        byte[] buffer = new byte[10 * 1024];
        do {
            try {
                bytesRead = in.stream.read(buffer);
                if (bytesRead != -1) {
                    byte[] previousBytes = allBytes;
                    allBytes = new byte[bytesRead + totalBytes];
                    System.arraycopy(previousBytes, 0, allBytes, 0, previousBytes.length);
                    System.arraycopy(buffer, 0, allBytes, totalBytes, bytesRead);
                    
                    totalBytes += bytesRead;
                } else {
                    in.stream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            
            // Log.d("JMATT", "Read " + bytesRead + " bytes out of a possible " + data.length);
        } while (bytesRead != -1);
        in.bytes = allBytes;
    }

}
